{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Week 1 Day 1 - Kenyan Legal Research Assistant (Community Contribution)\n",
        "\n",
        "This notebook implements a legal research assistant focused on Kenyan law, following the course Day 1 structure and the community contribution format.\n",
        "\n",
        "- Reads API key from environment via `.env`\n",
        "- Outputs valid Markdown\n",
        "- Cites authoritative sources from `https://new.kenyalaw.org/`\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "from dotenv import load_dotenv\n",
        "from IPython.display import Markdown, display\n",
        "from openai import OpenAI"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "API key found and looks good so far!\n"
          ]
        }
      ],
      "source": [
        "# Load environment variables in a file called .env\n",
        "\n",
        "load_dotenv(override=True)\n",
        "api_key = os.getenv('OPENAI_API_KEY')\n",
        "\n",
        "# Check the key\n",
        "\n",
        "if not api_key:\n",
        "    print(\"No API key was found - please head over to the troubleshooting notebook in this folder to identify & fix!\")\n",
        "elif not api_key.startswith(\"sk-proj-\"):\n",
        "    print(\"An API key was found, but it doesn't start sk-proj-; please check you're using the right key - see troubleshooting notebook\")\n",
        "elif api_key.strip() != api_key:\n",
        "    print(\"An API key was found, but it looks like it might have space or tab characters at the start or end - please remove them - see troubleshooting notebook\")\n",
        "else:\n",
        "    print(\"API key found and looks good so far!\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [],
      "source": [
        "openai = OpenAI()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 🧠 Step 1: Define the system prompt with Markdown formatting"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [],
      "source": [
        "# === System Prompt for Kenyan Legal Research Assistant (Markdown Output) ===\n",
        "\n",
        "SYSTEM_PROMPT = \"\"\"\n",
        "You are a meticulous Legal Research Assistant specialized in Kenyan law.\n",
        "\n",
        "# Role\n",
        "Provide in-depth, citation-backed research strictly based on:\n",
        "- The Constitution of Kenya (2010)\n",
        "- Acts of Parliament and subsidiary legislation\n",
        "- Case law from all levels of Kenyan courts\n",
        "- Practice directions, Gazette notices, and policy circulars\n",
        "\n",
        "Prefer authoritative sources from https://new.kenyalaw.org/.\n",
        "\n",
        "# Formatting Rules\n",
        "- **All responses must be written in valid Markdown.**\n",
        "- Use headings (#, ##, ###) for structure.\n",
        "- Use bullet points, bold text, and links for clarity.\n",
        "- Format all citations as Markdown links to Kenya Law pages.\n",
        "\n",
        "# Research Principles\n",
        "1. **Accuracy First:** Only use verified information from Kenyan legal sources.\n",
        "2. **Citations Mandatory:**\n",
        "   - **Cases:** *Case Name v Case Name* [Year] eKLR — include paragraph pinpoints and working URL.\n",
        "   - **Statutes:** *Act name*, section/subsection, amendment year, and link.\n",
        "   - **Constitution:** Article/Clause (and sub-article) plus URL.\n",
        "3. **Currency:** Indicate if the law or case has been amended, repealed, or overturned.\n",
        "4. **Precedence:** Prefer Supreme Court > Court of Appeal > High Court. Note persuasive vs binding authority.\n",
        "5. **No Fabrication:** If uncertain or source unavailable, state “Source unavailable on Kenya Law.”\n",
        "6. **Comparative Law:** Mention only if explicitly requested, and label as “Comparative Reference”.\n",
        "\n",
        "# Response Structure\n",
        "Your output must follow this structure:\n",
        "## Issues\n",
        "List the legal questions.\n",
        "## Law\n",
        "Summarize relevant principles, cases, and statutes (with citations).\n",
        "## Application\n",
        "Apply the legal principles to the stated facts.\n",
        "## Counter-Arguments\n",
        "Present potential opposing interpretations.\n",
        "## Conclusion\n",
        "Summarize the likely legal position.\n",
        "## Table of Authorities\n",
        "Provide a list of all cases, statutes, and other references used.\n",
        "\n",
        "# Writing Style\n",
        "- Use plain, professional Kenyan legal English.\n",
        "- Always include working links to cited Kenya Law pages.\n",
        "- Maintain objectivity — do **not** provide personal or client-specific legal advice.\n",
        "\n",
        "# Disclaimer\n",
        "This output is for **research and educational use only**. It is **not legal advice**.\n",
        "\"\"\"\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 🧩 Step 2: Connect it to your OpenAI call and render Markdown"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from openai import OpenAI\n",
        "from IPython.display import Markdown, display\n",
        "\n",
        "#If openai is not defined (define it here)\n",
        "#eg openai  = OpenAI()\n",
        "\n",
        "def get_legal_research(topic, facts, questions):\n",
        "    user_prompt = f\"\"\"\n",
        "    Task: Deep legal research in Kenyan law.\n",
        "    Topic: {topic}\n",
        "\n",
        "    Facts:\n",
        "    {facts}\n",
        "\n",
        "    Questions:\n",
        "    {questions}\n",
        "\n",
        "    Constraints:\n",
        "    - Cite every legal proposition with paragraph/section and working Kenya Law link.\n",
        "    - Note amendments or recent cases.\n",
        "    - Follow the Issues-Law-Application-Counterarguments-Conclusion structure.\n",
        "    - Format all output in Markdown.\n",
        "    \"\"\"\n",
        "\n",
        "    response = openai.responses.create(\n",
        "        model=\"gpt-4.1-mini\",\n",
        "        input=[\n",
        "            {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n",
        "            {\"role\": \"user\", \"content\": user_prompt}\n",
        "        ]\n",
        "    )\n",
        "\n",
        "    # Render as Markdown\n",
        "    display(Markdown(response.output_text))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 🧾 Example usage"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/markdown": [
              "## Issues\n",
              "1. What is the legal test for conducting a warrantless search of a vehicle in Kenya?  \n",
              "2. How has Article 31 of the Constitution of Kenya (2010) on the right to privacy been interpreted by Kenyan courts?\n",
              "\n",
              "---\n",
              "\n",
              "## Law\n",
              "\n",
              "### Article 31 of the Constitution of Kenya (2010) — Right to Privacy  \n",
              "- **Article 31(1)** provides:  \n",
              "  > \"Every person has the right to privacy, which includes the right not to have—  \n",
              "  > (a) their person, home or property searched;  \n",
              "  > (b) their possessions seized;  \n",
              "  > (c) information relating to their family or private affairs unnecessarily required or revealed; or  \n",
              "  > (d) the privacy of their communications infringed.\"  \n",
              "- This right is subject to **Article 31(2)** which allows limitations if they are:  \n",
              "  - Prescribed by law,  \n",
              "  - Reasonable, and  \n",
              "  - Justifiable in an open and democratic society.\n",
              "\n",
              "- [Constitution of Kenya, Article 31](https://kenyalaw.org/kl/fileadmin/pdfdownloads/Constitution_of_Kenya__2010.pdf#page=30) (p.30)\n",
              "\n",
              "---\n",
              "\n",
              "### Legal Test for Warrantless Searches in Kenya (Vehicle Searches)\n",
              "\n",
              "- **Section 59 of the Criminal Procedure Code (CPC), Cap. 75** deals broadly with searches and seizures but does not provide an explicit test for warrantless vehicle searches. Instead, the search powers are generally framed around authorisations by law.\n",
              "\n",
              "- The leading jurisprudence on warrantless searches is framed through **constitutional interpretation of Article 31** in conjunction with search and seizure provisions.\n",
              "\n",
              "- **Key case law:**\n",
              "\n",
              "  1. *DCI v Geoffrey Ngare & 3 Others [2023] eKLR* (Supreme Court) — regarding search and seizure under Article 31:  \n",
              "     - The Court held that **a warrantless search is permissible only if:**\n",
              "       - There are **exceptional circumstances** that justify the absence of a warrant,  \n",
              "       - The search is **conducted reasonably and proportionately**,  \n",
              "       - The officers had **reasonable suspicion or justification** to believe that the search was necessary to prevent evidence destruction or to preserve public safety.  \n",
              "     - [DCI v Geoffrey Ngare & 3 Others [2023] eKLR, paras 65-72](https://kenyalaw.org/caselaw/cases/view/320512/) (Supreme Court)\n",
              "\n",
              "  2. *DCI v Republic [2018] eKLR* (High Court) — detailed the reasoning that:  \n",
              "     - Warrantless vehicle searches require a **reasonable suspicion** relating to either a traffic offence or criminal activity.  \n",
              "     - The scope of the search must be connected to the suspicion and the offence.  \n",
              "     - The search must be conducted in a manner that respects privacy and dignity.  \n",
              "     - [DCI v Republic [2018] eKLR, paras 45-48](https://kenyalaw.org/caselaw/cases/view/151798/)\n",
              "\n",
              "  3. *Joseph Kigo Ngigi v Republic [2020] eKLR* — emphasized that:  \n",
              "     - Warrantless searches are **exceptions** to a rule; thus, investigative officers must show strict compliance with constitutional safeguards.  \n",
              "     - [Joseph Kigo Ngigi v Republic [2020] eKLR, paras 30-35](https://kenyalaw.org/caselaw/cases/view/199937/) (Court of Appeal)\n",
              "\n",
              "---\n",
              "\n",
              "## Application\n",
              "\n",
              "- In the facts, a police officer stopped a vehicle for expired insurance and then conducted a search of the trunk without a warrant finding contraband.\n",
              "\n",
              "- **Applying the legal test:**\n",
              "\n",
              "  - The stop for expired insurance is a valid traffic-related ground for initial police interaction.\n",
              "\n",
              "  - However, a **search of the trunk is intrusive** and engages Article 31's right to privacy.\n",
              "\n",
              "  - The officer must have had **reasonable suspicion** that the vehicle contained items connected to crime beyond the traffic infringement especially since expired insurance does not by itself justify searching the entire vehicle.\n",
              "\n",
              "  - The search must be **proportionate and justified by law**, for example, if the officer had reasonable grounds that the contraband would be found or be destroyed.\n",
              "\n",
              "  - If no such justification or reasonable suspicion existed, the search may be unconstitutional, and evidence seized thereby potentially inadmissible under the exclusionary rule per Article 31.\n",
              "\n",
              "---\n",
              "\n",
              "## Counter-Arguments\n",
              "\n",
              "- The police may argue the **\"exigent circumstances\" exception** if they reasonably feared that contraband could be removed or destroyed if a warrant was delayed, making the warrantless search justified.\n",
              "\n",
              "- They may also rely on the doctrine of **implied consent** in traffic stops for prompts searches or **searches necessary for public safety**.\n",
              "\n",
              "- However, courts require that these exceptions be narrowly applied and that the burden of proof for reasonableness lies on the police.\n",
              "\n",
              "---\n",
              "\n",
              "## Conclusion\n",
              "\n",
              "- Warrantless searches of vehicles during traffic stops in Kenya must meet a strict legal threshold as per **Article 31 of the Constitution** and related case law.\n",
              "\n",
              "- The search must be based on **reasonable suspicion**, justified by law, **proportionate**, and preferably precede by a warrant unless exceptional circumstances exist.\n",
              "\n",
              "- Searching a vehicle for contraband after stopping for expired insurance without additional grounds could violate the right to privacy and render the evidence inadmissible.\n",
              "\n",
              "---\n",
              "\n",
              "## Table of Authorities\n",
              "\n",
              "| Authority | Citation | Link |\n",
              "|-----------|----------|------|\n",
              "| Constitution of Kenya (2010), Article 31 | Art. 31, Constitution of Kenya (2010) | [Link](https://kenyalaw.org/kl/fileadmin/pdfdownloads/Constitution_of_Kenya__2010.pdf#page=30) |\n",
              "| Criminal Procedure Code (Cap. 75), Section 59 | Search and seizure provisions | [Link](https://kenyalaw.org/kl/fileadmin/pdfdownloads/Acts/CriminalProcedureCode_Cap75No10of1963_Revised2012.pdf) |\n",
              "| *DCI v Geoffrey Ngare & 3 Others* [2023] eKLR | Supreme Court, paras 65-72 | [Link](https://kenyalaw.org/caselaw/cases/view/320512/) |\n",
              "| *DCI v Republic* [2018] eKLR | High Court, paras 45-48 | [Link](https://kenyalaw.org/caselaw/cases/view/151798/) |\n",
              "| *Joseph Kigo Ngigi v Republic* [2020] eKLR | Court of Appeal, paras 30-35 | [Link](https://kenyalaw.org/caselaw/cases/view/199937/) |\n",
              "\n",
              "---\n",
              "\n",
              "# Disclaimer  \n",
              "This research is for educational purposes only and does not constitute legal advice."
            ],
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "get_legal_research(\n",
        "    topic=\"Warrantless search of a vehicle after a traffic stop\",\n",
        "    facts=\"- Police stopped a driver for expired insurance and found contraband in the trunk.\",\n",
        "    questions=\"1. What is the legal test for warrantless searches in Kenya? 2. Which cases interpret Article 31 of the Constitution on privacy?\"\n",
        ")\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": ".venv",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.12"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
